package com.gframework.boot.mvc.controller.convert;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.Date;

import org.slf4j.LoggerFactory;

import com.gframework.autoconfigure.mvc.MvcProperties;

/**
 * 基于时间戳的前后端通讯日期格式统一转换器.
 * <p>
 * 时间戳是表示时间最为精准的数据，为了兼容各种时区，年表等问题，通过时间戳来进行时间传递，是最为合理的。
 * 服务端只保存自己时区的时间，任何客户端取到的都是时间戳，然后根据客户端自己的Locale和时区以及年表进行时间的格式化。
 * </p>
 * 
 * @since 1.0.0
 * @author Ghwolf
 */
@SuppressWarnings("serial")
public class TimestampUnifiedDateConverter implements UnifiedDateConverter {

	/**
	 * 日期转换时区偏移位
	 */
	private final ZoneOffset zoneOffset;

	public TimestampUnifiedDateConverter(MvcProperties properties) {
		this.zoneOffset = ZoneOffset.of(properties.getConvertDateZoneOffset());
		LoggerFactory.getLogger(TimestampUnifiedDateConverter.class).info("====> 已启用基于时间戳的前后端统一日期格式，时区：{}",
				properties.getConvertDateZoneOffset());
	}

	@Override
	public Date stringToDate(String source) throws UnifiedDateConvertException {
		return new Date(toLong(source));
	}

	@Override
	public Object dateToStringOrNumber(Date date) {
		return date.getTime();
	}

	@Override
	public LocalDate stringToLocalDate(String source) throws UnifiedDateConvertException{
		LocalDateTime time = this.stringToLocalDateTime(source);
		return time == null ? null : LocalDate.from(time); 
	}

	@Override
	public Object localDateToStringOrNumber(LocalDate date) {
		return date.atStartOfDay().toEpochSecond(zoneOffset) * 1000L;
	}

	@Override
	public LocalDateTime stringToLocalDateTime(String source)throws UnifiedDateConvertException {
		return LocalDateTime.ofEpochSecond(toLong(source) / 1000, 0, zoneOffset);
	}

	@Override
	public Object localDateTimeToStringOrNumber(LocalDateTime date) {
		return date.toEpochSecond(zoneOffset) * 1000L;
	}

	private long toLong(String source) throws UnifiedDateConvertException{
		try {
			return Long.parseLong(source);
		} catch(NumberFormatException e) {
			throw new UnifiedDateConvertException("当前正在使用基于时间戳的统一前后端通讯协议，class:TimestampUnifiedDateConverter，但是接收到的却不是时间戳：" + source,e);
		}
	}

}
